package javaeSE.reflection;

import java.lang.reflect.*;
// 反射基础
public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        System.out.println("类名.class");
        System.out.println(Test.class);
        // 2 实例.getClass()
        Class c4 = test.getClass();
        System.out.println(Test.class == c4);
     /*   try {
            Test testn = (Test)c4.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }*/
        //第三种方式获取Class对象
        try {
            //注意此字符串必须是真实路径，就是带包名的类路径，包名.类名
            Class stuClass3 = Class.forName("javaeSE.reflection.Test");
                System.out.println(stuClass3);
                System.out.println(c4);
                System.out.println(Test.class);
            } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Constructor[] constructors ;
        Constructor constructor ;
        Constructor constructorss;
        // getConstructors方法获取类中 所有的public类型的构造方法
        constructors = c4.getDeclaredConstructors(); //所有构造方法
        System.out.println("所有构造方法："+constructors);

        //通过getModifiers可以得到构造方法的类型，getParameterTypes可以得到构造方法的 所有参数
        for (int i = 0; i < constructors.length; i++) {
            System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数：");
            Class[] parametertypes = constructors[i].getParameterTypes();
            for (int j = 0; j < parametertypes.length; j++) {
                System.out.print(parametertypes[j].getName() + "，");
            }
            System.out.println("");
        }

      /*  我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法，
        这里注意是getDeclaredConstructor()不是  getDeclaredConstructors() ，
        所以返回的是一个Class对象而不是一个Class数组。*/
        // 获取一个public 类型的构造方法
        try {
            constructor = c4.getDeclaredConstructor();
            System.out.print(Modifier.toString(constructor.getModifiers()));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


        //   如果我们想获取有两个参数分别为int和String类型的构造方法，代码如下：
        Class[] p = {int.class,String.class,int.class};
        Class[] p4 = {String.class};
        System.out.println();
        System.out.println("p:"+p);
        try {
            constructorss = c4.getDeclaredConstructor(p);
            System.out.print(Modifier.toString(constructorss.getModifiers()) + "参数:");
            Class[] parametertypes = constructorss.getParameterTypes();
            for (int j = 0; j < parametertypes.length; j++) {
                System.out.print(parametertypes[j].getName() + " ");
            }
            // 获取类实例
            Test test2 = (Test) constructorss.newInstance(24,"HuangLinqing",20);
            test2.test();
            test2.welcome("hello");

            Field field = c4.getDeclaredField("name");
            field.setAccessible(true);   //获取类的私有字段并修改值
            field.set(test2,"代码男人a ");
            System.out.println(test2);
            // 调用私有方法也需要得到类的实例
            Method method = c4.getDeclaredMethod("welcome",p4);
            method.setAccessible(true); // 访调类的私有方法
            Object arg1s[] = {"欢迎关注代码男人技术公众号"};
            method.invoke(test2,arg1s);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

     /*   Class[] p = {String.class};
        constructors = c4.getDeclaredConstructor(p);
        constructors.setAccessible(true);  私有构造函数处理方式
        constructors.newInstance("HuangLinqing");*/
    }


    private int age;
    private String name;
    private int testint;
    public Test(int age) {
        this.age = age;
    }
    private void setName(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

    public Test(int age, String name, int testint) {
        this.age = age;
        this.name = name;
        this.testint = testint;
        System.out.println();
        System.out.println(this.age);
        System.out.println(this.name);
        System.out.println(this.testint);

    }

    private Test(String name) {
        this.name = name;
        System.out.println(this.name);
    }

    public Test() {

    }

    private void welcome(String tips){
        System.out.println(tips);
    }

    private void test(){
        System.out.println("test");
    }

    @Override
    public String toString() {
        return "Test{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", testint=" + testint +
                '}';
    }



}
